package com.aplink.generic.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;

import com.aplink.generic.controller.GenericApplication;
import com.aplink.generic.network.GenericFile;

public class BitmapUtis {
    private static BitmapUtis sInstance = null;

    public static BitmapUtis getInstance() {
        if (BitmapUtis.sInstance == null) {
            BitmapUtis.sInstance = new BitmapUtis();
        }
        return BitmapUtis.sInstance;
    }

    private BitmapUtis() {
    }

    private int calculateInSampleSize(final BitmapFactory.Options options,
            final int reqWidth, final int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if ((height > reqHeight) || (width > reqWidth)) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            while (((halfHeight / inSampleSize) > reqHeight)
                    && ((halfWidth / inSampleSize) > reqWidth)) {
                inSampleSize *= 2;
            }

            long totalPixels = (width * height) / inSampleSize;

            final long totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels > totalReqPixelsCap) {
                inSampleSize *= 2;
                totalPixels /= 2;
            }
        }
        return inSampleSize;
    }

    public GenericFile createTempFile(final String filename) {
        final GenericFile genericFile = new GenericFile();
        final String extStorageDirectory = Environment
                .getExternalStorageDirectory().toString();
        final String applicationName = GenericApplication.getInstance()
                .getApplicationName();
        File file = new File(extStorageDirectory + "/" + applicationName);
        if (!file.exists()) {
            file.mkdir();
        }

        try {
            file = File.createTempFile(filename, ".jpg", new File(
                    extStorageDirectory + "/" + applicationName));

            LogUtil.info("saved: " + "file://" + file.toString(), "saved file",
                    getClass());
            genericFile.setLocalPath(file.toString());
            genericFile.setExtension(".jpg");
            genericFile.setName(filename);
            return genericFile;
        } catch (final Exception e) {
            LogUtil.error(e.getMessage(), "save file:" + file.toString(),
                    getClass());
        }
        return null;
    }

    public Bitmap decodeSampledBitmapFromFile(final String filename,
            final int reqWidth, final int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filename, options);
        getDefaultOptions().inSampleSize = calculateInSampleSize(options,
                reqWidth, reqHeight);
        return BitmapFactory.decodeFile(filename, getDefaultOptions());
    }

    public Bitmap decodeSampledBitmapFromResource(final Resources res,
            final int resId, final int reqWidth, final int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
        getDefaultOptions().inSampleSize = calculateInSampleSize(options,
                reqWidth, reqHeight);
        return BitmapFactory.decodeResource(res, resId, getDefaultOptions());
    }

    public Bitmap decodeThumbnailBitmapFromFile(final String filename) {
        return decodeSampledBitmapFromFile(filename, 320, 240);
    }

    public Bitmap decodeThumbnailBitmapFromResource(final Resources res,
            final int resId) {
        return decodeSampledBitmapFromResource(res, resId, 320, 240);
    }

    public GenericFile download(final String physicalPath) {
        final GenericFile genericFile = new GenericFile();
        try {
            final String extStorageDirectory = Environment
                    .getExternalStorageDirectory().toString();
            final String applicationName = GenericApplication.getInstance()
                    .getApplicationName();
            final File file = new File(extStorageDirectory + "/"
                    + applicationName);
            if (!file.exists()) {
                file.mkdir();
            }
            final URL url = new URL(physicalPath);
            String fileName = null;
            String fileExtension = null;
            final URLConnection connection = url.openConnection();
            final String disposition = connection
                    .getHeaderField("Content-Disposition");

            if (disposition != null) {
                final int index = disposition.indexOf("filename=");
                if (index > 0) {
                    fileName = disposition.substring(index + 10,
                            disposition.length() - 1);
                }
            } else {
                fileName = physicalPath.substring(
                        physicalPath.lastIndexOf("/") + 1,
                        physicalPath.length());
            }
            final int index = fileName.lastIndexOf(".");
            fileExtension = fileName.substring(index, fileName.length());
            final InputStream input = connection.getInputStream();
            final File storagePath = new File(extStorageDirectory + "/"
                    + applicationName, fileName);

            genericFile.setLocalPath(storagePath.toString());
            genericFile.setName(fileName);
            genericFile.setPhysicalPath(physicalPath);
            genericFile.setExtension(fileExtension);

            if (storagePath.exists()) {
                LogUtil.info("Exists: " + "file://" + storagePath.toString(),
                        "Download file:" + physicalPath, getClass());
                return genericFile;
            }
            final OutputStream output = new FileOutputStream(storagePath);
            try {
                final byte[] buffer = new byte[1024];
                int bytesRead = 0;
                while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
                    output.write(buffer, 0, bytesRead);
                }
                LogUtil.info(
                        "downloaded: " + "file://" + storagePath.toString(),
                        "Download file:" + physicalPath, getClass());
                return genericFile;
            } finally {
                output.close();
            }
        } catch (final IOException e) {
            LogUtil.error(e.getMessage(), "Download file:" + physicalPath,
                    getClass());
        }
        return null;
    }

    private BitmapFactory.Options getDefaultOptions() {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        options.inDither = false;
        options.inJustDecodeBounds = false;
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inTempStorage = new byte[16 * 1024];
        return options;
    }

    public GenericFile savebitmap(final Bitmap bitmap) {
        final String filename = null;
        return this.savebitmap(filename, bitmap);
    }

    public GenericFile savebitmap(final String filename, final Bitmap bitmap) {
        final GenericFile genericFile = new GenericFile();
        final String extStorageDirectory = Environment
                .getExternalStorageDirectory().toString();
        final String applicationName = GenericApplication.getInstance()
                .getApplicationName();
        OutputStream outStream = null;

        File file = new File(extStorageDirectory + "/" + applicationName);
        if (!file.exists()) {
            file.mkdir();
        }
        file = new File(extStorageDirectory + "/" + applicationName, filename
                + ".jpg");
        try {
            outStream = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 70, outStream);
            outStream.flush();
            outStream.close();
            LogUtil.info("saved: " + "file://" + file.toString(), "saved file",
                    getClass());
            genericFile.setLocalPath(file.toString());
            genericFile.setExtension(".jpg");
            genericFile.setName(filename);
            return genericFile;
        } catch (final Exception e) {
            LogUtil.error(e.getMessage(), "save file:" + file.toString(),
                    getClass());
        }
        return null;
    }
}
